1 Introduction

This document contains the results and analysis of my second experiment for my first Qualifying Paper towards the PhD in Linguistics at Stanford University1.

2 Methods

2.1 The Experiment

The experiment analyzed herein was an online maze task study, wherein participants read a sentence such as “David is a congressperson from Virginia. He likes cycling.” For each of the 20 critical items, participants were randomly assigned to one of four conditions, the critical regions of which are enumerated and exemplified here:

  1. Male-congruent: David is a congressman
  2. Male-neutral: David is a congressperson
  3. Female-congruent: Sally is a congresswoman
  4. Female-neutral: Sally is a congressperson

Participants proceeded through the sentences by pressing a keyboard key which corresponded to the grammatical continuation of the sentence, and reading pair of grammatical and distractor items at a time. They were then asked attention check questions at the end of each sentence; attention check questions never explicitly invoked gender. Rather, they asked about the character’s home states. For a hands-on look at the experiment, you can click here to go to the same webpage particpants were directed to for the task.

2.2 Participants

We originally ran the experiment on 200 participants, recruited through the online participant recruitment platform Prolific. The mean time of the experiment was 5.39 minutes, and participants were paid $1.75 for their participation2. The only restrictions placed on participants were that they:

  1. Were born in the United States
  2. Lived in the United States at the time of participation
  3. Spoke English as a first language
  4. Had not participated in the norming study for the stimuli

These requirements were implemented in order to assure that speakers came from at least somewhat similar linguistic backgrounds, as certain lexical items in the study (such as congressperson) are quite localized to the United States.

After this initial run of the experiment, we found that there was a dearth of conservative or Republican-aligned participants. As a result, we ran the experiment again, this time on 98 self-identified Republicans. This was achieved by adding a filter on Prolific so that only Republican-identified individuals could see the task. The rest of the experiment, including payment, was exactly the same, except that an additional disclaimer that participants could not use the FireFox browser experiment, after the first run revealed an incompatibility between JavaScript and FireFox. The two runs of the experiment amounted in a total of 298 participants who completed the task.

3 Prepping the Data

Before we can do much of anything with the data, we need to make sure it’s usable! This means filtering out all unimportant or extraneous trials, running exclusion criteria, and adding additional trial and item-level data that will be necessary later in the analysis.

3.1 Packages

For this analysis, we require the following packages:

library(ggplot2) 
library(tidyverse) 
library(lme4) 
library(stringr)
library(languageR)
library(lmerTest)
library(reshape2)

source("helpers.R")
theme_set(theme_minimal())

3.2 Reading in the Data

In the first instance, we need to read in the data, which has been pre-merged from both runs of the experiment. We will also in this chunk filter out all of the example trials, as well as all the data points that are from non-critical trials.

all_data <- read.csv('merged_all.csv') %>%
  filter(trial_id!= 'example') %>%
  filter(region=='critical')

3.3 Running Exclusion Criteria

Now, we want to exclude any participants who failed to answer at least 80% of the attention check questions correctly. We do this by creating a list of all participants who scored less than 80% on these checks, and then cross-referencing this list with all data points, removing any data points whose participants were in the exclusion list.

exclusion <- all_data %>% group_by(workerid) %>%
  summarise(accuracy = mean(response_correct)) %>%
  mutate(exclude = ifelse(accuracy < 0.80,'Yes','No')) %>% 
  filter(exclude == 'Yes')

all_data <- all_data[!(all_data$workerid %in% exclusion$workerid),] %>%
  filter(rt !='null')

We also want to filter out all trials in which the reading time for the critical item was more than 2.5 standard deviations from the mean reading time on that lexical item across all participants.

all_data <- all_data %>% group_by(trial_id) %>% mutate(id_mean = mean(log(rt))) %>% mutate(exclusion = (log(rt) < mean(log(rt)) - 2sd(log(rt))|(log(rt) > mean(log(rt)) + 2sd(log(rt))))) %>% ungroup() %>% filter(exclusion==FALSE)

This results in 238 trials being removed from the 5580 we got after the by-participant exclusions. We now have 5342 trials we can use for analysis.

3.4 Adding in Additional Important Trial Information

Now that we have only the rows we want, let’s add some new columns, which will contain important information for each data point. Here, we will be adding:

  • Gender Ideology Subscores
  • Trial Genders
  • Trial Morphology Types
  • Critical Item Length & Length-Controlled Residuals
  • Trial Congruency
  • Partipant Political Affiliation

Ideally, I would’ve added all of these but the first when I actually created the stimuli and logged responses, but I forgot to! Luckily, R allows us to do this post-hoc fairly straightforwardly… which is good, since these features will be critical in our data visualization and analysis.

3.4.1 Defining Gender Subscores


The question under investigation here is whether or not individuals’ conceptions of gender affect how they process gendered and gender-neutral forms of English personal and professional titles.

In order to examine this, we need to quanify participants’ ideological views! Here we have adopted the 13-item Social Roles Questionnaire put forth in Baber & Tucker (2006). Questions 1-5 correlate to the ‘Gender Transcendent’ subscale, and questions 6-13 correspond to the ‘Gender Linked’ subscale. Each item is scored on a scale of 0-100. So, the first thing we want to do is make two lists of columns which correspond to these two subscales, since the questions are stored individually in the data:

gender_transcendence_cols <- c('subject_information.gender_q1','subject_information.gender_q2','subject_information.gender_q3','subject_information.gender_q4','subject_information.gender_q5')

gender_linked_cols <- c('subject_information.gender_q6','subject_information.gender_q7','subject_information.gender_q8','subject_information.gender_q9','subject_information.gender_q10','subject_information.gender_q11','subject_information.gender_q12','subject_information.gender_q13')


Now we can use the mutate() method on all_data to add two new columns, one for each subscale. We tell R to take the means of the specified columns in [column_names] of all_data for each individual row: rowMeans(all_data[column_names]). We also have to subtract this mean from 100 in the case of the ‘Gender Transcendent’ subscale, since it is inversely scored. Finally, we can create an average total score regardless of subscores, simply by meaning the two subscores we already have.

all_data <- all_data %>%
  mutate(gender_trans = 100 - (rowMeans(all_data[gender_transcendence_cols]))) %>%
  mutate(gender_link = rowMeans(all_data[gender_linked_cols])) 

gender_all = c('gender_trans','gender_link')

all_data <- all_data %>%
  mutate(gender_total = rowMeans(all_data[gender_all]))

3.4.2 Adding Gender


We also want to add whether the trial included a female or male referent (but also, like, destroy the binary!). In order to do this, we’ll just add a trial_gender column that says ‘female’ if the condition was either ‘neutral_female’ or ‘congruent_female’. Otherwise, we want the trial_gender to say ‘male’.

all_data <- all_data %>%
  mutate(trial_gender = ifelse(condition=='neutral_female' | condition == 'congruent_female','female','male'))

all_data %>%
  select(workerid,rt,condition,trial_id,trial_gender)

3.4.3 Adding Morphology Type


Now we want to add whether or not the lexeme’s neutral form is developed by compounding (as in ‘congress-person’) or by the adoption of the male form (as in ‘actor’ being used more for both men and women). In this study, we only have six lexemes of the latter type, so we’ll just tell R to assign those a morph_type value of ‘adoption’ (for ‘male adoption’), and all else will be assigned a value of ‘compound’.

all_data <- all_data%>%
  mutate(morph_type = ifelse(lexeme!= 'actor' & lexeme!= 'host' & lexeme !='hunter' & lexeme!= 'villain' & lexeme!= 'heir' & lexeme!= 'hero','compound','adoption'))

all_data %>%
  select(rt,lexeme,morph_type)

3.4.4 Adding Form Length & Length-Controlled Residuals


Another important factor we want to explore is the length of the critical item! In order to add this, we simply create a new column form_length and tell R to input as that column’s value the length of the string that appears in that row’s form column, which corresponds to the orthograpic form of the critical item in that trial. Note that this will include spaces in the count!

all_data <- all_data %>%
  mutate(form_length = str_length(form))

simple_model <- lm(log(rt)~form_length, data = all_data)

all_data <- all_data %>%
  mutate(resid_rt = resid(simple_model))
summary(simple_model)

Call:
lm(formula = log(rt) ~ form_length, data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.8807 -0.3063 -0.0720  0.2406  3.2023 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 6.965847   0.022117 314.958  < 2e-16 ***
form_length 0.011405   0.002271   5.022 5.37e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4307 on 3411 degrees of freedom
Multiple R-squared:  0.00734,   Adjusted R-squared:  0.007049 
F-statistic: 25.22 on 1 and 3411 DF,  p-value: 5.374e-07

Now that we have these, we can run a simple linear regression which will show us the effect of orthographic length on reading time. Then we add a new column in the data which is the residual reading time, or the reading time in log space AFTER we control for the effects of orthographic length.

3.4.5 Adding Congruency Column


We also want to make sure we have a column which records whether or not the trial was gender-congruent (as in ‘Shelby is a congresswoman’) or gender neutral (as in ‘Shelby is a congressperson’). We add a trial_congruency column, which is valued as ‘congruent’ if that row’s condition is one of the two congruent conditions. Otherwise, it gets valued as ‘neutral’.

all_data <- all_data %>%
  mutate(trial_congruency = ifelse(condition=='congruent_male' | condition == 'congruent_female','congruent','neutral'))

3.4.6 Adding Large Political Macrocategories


Finally, we can classify participants by their particular political alignment; we can construe this broadly as “Republicans” vs. “Democrats”, with those who declined to state a preference, or placed themselves in the middle, as “Non-Partisan”.

all_data <- all_data %>%
  mutate(poli_party = ifelse(subject_information.party_alignment == 1 | subject_information.party_alignment == 2,'Republican',ifelse(subject_information.party_alignment == 4 | subject_information.party_alignment == 5,'Democrat','Non-Partisan')))

4 Data Visualization

Now we can start analysing the data by means of data visualization.

inauguration_2021 = c("#5445b1", "#749dae", "#f3c483", "#5c1a33", "#cd3341","#f7dc6a")

4.1 Ideology by Age

ggplot(all_data, aes(x=subject_information.age, y=gender_total, color=poli_party)) + 
  geom_point(alpha=.5) + 
  geom_smooth(method = 'lm', size=1.2)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 20 rows containing non-finite values (stat_smooth).
Warning: Removed 20 rows containing missing values (geom_point).

4.2 Reading Time by Gender Ideology

ggplot(all_data, aes(x=gender_total, y=resid_rt, color=trial_congruency)) + 
  geom_point(alpha=.5) + 
  geom_smooth(method = 'lm', size=1.2) + 
  theme_minimal()
`geom_smooth()` using formula 'y ~ x'

4.3 Reading Time by Age

ggplot(all_data, aes(x=subject_information.age, y=resid_rt, color=trial_congruency, linetype=morph_type)) + 
  geom_point(alpha=.5) + 
  geom_smooth(method = 'lm', size=1.2)
`geom_smooth()` using formula 'y ~ x'
Warning: Removed 20 rows containing non-finite values (stat_smooth).
Warning: Removed 20 rows containing missing values (geom_point).

4.4 Reading Time by Congruency and Gender

agg_speaker_mean_con <- all_data %>%
  group_by(condition,workerid) %>%
  summarize(MeanRT=mean(resid_rt))
`summarise()` has grouped output by 'condition'. You can override using the `.groups` argument.
all_data %>%
  group_by(condition,trial_gender) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender)) + 
  geom_point(size=3) + 
  geom_jitter(data = agg_speaker_mean_con, aes(y=MeanRT),alpha=.1,color='darkred') + 
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  scale_color_manual(values = inauguration_2021) + 
  theme_minimal()
`summarise()` has grouped output by 'condition'. You can override using the `.groups` argument.

4.5 Reading Time by Congruency, Gender, and Lexical Item

all_data %>%
  group_by(condition,trial_gender,trial_congruency,lexeme) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender,shape=trial_congruency)) + 
  geom_point(size=3) +
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  facet_wrap(~ lexeme) +
  theme(axis.text.x = element_text(angle = 45, vjust = .7, hjust=.7)) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~lexeme)
`summarise()` has grouped output by 'condition', 'trial_gender', 'trial_congruency'. You can override using the `.groups` argument.

4.5.1 Male Adoptions Only

all_data %>%
  filter(morph_type == "adoption") %>%
  group_by(condition,trial_gender,trial_congruency,lexeme) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender,shape=trial_congruency)) + 
  geom_point(size=3) +
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  facet_wrap(~ lexeme) +
  theme(axis.text.x = element_text(angle = 45, vjust = .7, hjust=.7)) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~lexeme)
`summarise()` has grouped output by 'condition', 'trial_gender', 'trial_congruency'. You can override using the `.groups` argument.

4.5.2 Compounds only

all_data %>%
  filter(morph_type == "compound") %>%
  group_by(condition,trial_gender,trial_congruency,lexeme) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender,shape=trial_congruency)) + 
  geom_point(size=3) +
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  facet_wrap(~ lexeme) +
  theme(axis.text.x = element_text(angle = 45, vjust = .7, hjust=.7)) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~lexeme)
`summarise()` has grouped output by 'condition', 'trial_gender', 'trial_congruency'. You can override using the `.groups` argument.

4.6 Raw Reading Time by Trial Gender

temp <- all_data %>%
  group_by(trial_gender) %>%
  summarize(MeanRT = mean(rt), CI.Low = ci.low(rt), CI.High = ci.high(rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High)

dodge = position_dodge(.9)
ggplot(data=temp, aes(x=trial_gender,y=MeanRT,fill=trial_gender)) + 
  geom_bar(stat='identity',position=dodge) + 
  geom_errorbar(aes(ymin=YMin,ymax=YMax),width=.25,position=dodge) +
  theme(legend.position = 'none')

dodge = position_dodge(.9)

all_data %>% 
  group_by(trial_gender) %>%
  summarize(MeanRT = mean(resid_rt)) %>%
  ggplot(aes(x=trial_gender,y=MeanRT,fill=trial_gender)) + 
  geom_bar(stat='identity',position=dodge) + 
  theme(legend.position = 'none')

4.7 Reading Time Residuals by Congruency

dodge = position_dodge(.9)

all_data %>% 
  group_by(trial_congruency) %>%
  summarize(MeanRT = mean(resid_rt)) %>%
  ggplot(aes(x=trial_congruency,y=MeanRT,fill=trial_congruency)) + 
  geom_bar(stat='identity',position=dodge) + 
  theme(legend.position = 'none')

4.8 By Morphological Type and Gender

all_data %>%
  group_by(condition,trial_gender,morph_type) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender)) + 
  geom_point(size=3) + 
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~morph_type) + 
  theme(axis.text.x = element_text(angle=45, vjust = 0.5))
`summarise()` has grouped output by 'condition', 'trial_gender'. You can override using the `.groups` argument.

4.9 Task Familiarity

agg_speaker_trial <- all_data %>%
  group_by(condition,workerid) %>%
  summarize(MeanRT=mean(resid_rt))
`summarise()` has grouped output by 'condition'. You can override using the `.groups` argument.
all_data %>%
  group_by(trial_no) %>%
  summarise(MeanRT = mean(rt)) %>%
  ggplot(aes(x=trial_no,y=MeanRT)) + 
  geom_point() + 
  geom_smooth() + 
  theme_minimal()
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

5 Model Analyses

6 Testing Models

test_model <- lm(resid_rt~trial_congruency*morph_type, data=all_data)
summary(test_model)

Call:
lm(formula = resid_rt ~ trial_congruency * morph_type, data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.8969 -0.3008 -0.0732  0.2419  3.1890 

Coefficients:
                                           Estimate Std. Error t value Pr(>|t|)    
(Intercept)                                 0.04150    0.01917   2.165 0.030431 *  
trial_congruencyneutral                    -0.02822    0.02683  -1.052 0.292930    
morph_typecompound                         -0.09979    0.02279  -4.378 1.23e-05 ***
trial_congruencyneutral:morph_typecompound  0.12246    0.03205   3.821 0.000135 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4285 on 3409 degrees of freedom
Multiple R-squared:  0.01041,   Adjusted R-squared:  0.009535 
F-statistic: 11.95 on 3 and 3409 DF,  p-value: 8.817e-08
test_model2 <- lm(resid_rt~trial_gender, data=all_data)
summary(test_model2)

Call:
lm(formula = resid_rt ~ trial_gender, data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-0.8772 -0.3069 -0.0719  0.2413  3.1987 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)
(Intercept)      -0.003498   0.010417  -0.336    0.737
trial_gendermale  0.007006   0.014743   0.475    0.635

Residual standard error: 0.4307 on 3411 degrees of freedom
Multiple R-squared:  6.619e-05, Adjusted R-squared:  -0.000227 
F-statistic: 0.2258 on 1 and 3411 DF,  p-value: 0.6347
compounds_only <- all_data %>%
  filter(morph_type == 'compound')
compounds_only <- compounds_only %>%
  mutate(ctrial_congruency = as.numeric(as.factor(trial_congruency))-mean(as.numeric(as.factor(trial_congruency)))) %>%
  mutate(ctrial_gender = as.numeric(as.factor(trial_gender))-mean(as.numeric(as.factor(trial_gender)))) %>%
  mutate(cgender_link = scale(gender_link)) %>%
  mutate(cgender_total = scale(gender_total))
compound_model <- lmer(resid_rt~ctrial_congruency*ctrial_gender*cgender_total + (1|workerid) + (1|lexeme),data = compounds_only)
summary(compound_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: resid_rt ~ ctrial_congruency * ctrial_gender * cgender_total +  
    (1 | workerid) + (1 | lexeme)
   Data: compounds_only

REML criterion at convergence: 1747.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.9415 -0.6037 -0.1168  0.4786  6.6039 

Random effects:
 Groups   Name        Variance Std.Dev.
 workerid (Intercept) 0.071787 0.26793 
 lexeme   (Intercept) 0.009879 0.09939 
 Residual             0.098696 0.31416 
Number of obs: 2392, groups:  workerid, 175; lexeme, 14

Fixed effects:
                                                Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)                                     -0.01243    0.03402   30.36022  -0.365   0.7174    
ctrial_congruency                                0.09596    0.01301 2208.36825   7.377 2.27e-13 ***
ctrial_gender                                    0.02720    0.01302 2209.23896   2.089   0.0368 *  
cgender_total                                    0.05503    0.02126  173.18802   2.589   0.0104 *  
ctrial_congruency:ctrial_gender                 -0.03472    0.02608 2210.39826  -1.331   0.1832    
ctrial_congruency:cgender_total                  0.01164    0.01300 2206.77070   0.895   0.3707    
ctrial_gender:cgender_total                     -0.01642    0.01305 2209.79268  -1.259   0.2082    
ctrial_congruency:ctrial_gender:cgender_total   -0.02910    0.02607 2209.09340  -1.116   0.2646    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                 (Intr) ctrl_c ctrl_g cgndr_ ctrl_cngrncy:ct_ ctrl_cngrncy:cg_ ctrl_g:_
ctrl_cngrnc       0.000                                                                
ctrial_gndr       0.000 -0.010                                                         
cgender_ttl       0.001  0.003  0.000                                                  
ctrl_cngrncy:ct_ -0.002  0.001  0.003 -0.001                                           
ctrl_cngrncy:cg_  0.002 -0.006 -0.002  0.011  0.001                                    
ctrl_gndr:_       0.000 -0.001  0.004  0.001  0.016           -0.011                   
ctrl_cn:_:_       0.000  0.002  0.015 -0.003  0.001            0.004            0.039  
adoptions_only <- all_data %>%
  filter(morph_type == 'adoption')
adoptions_only <- adoptions_only %>%
  mutate(ctrial_congruency = as.numeric(as.factor(trial_congruency))-mean(as.numeric(as.factor(trial_congruency)))) %>%
  mutate(ctrial_gender = as.numeric(as.factor(trial_gender))-mean(as.numeric(as.factor(trial_gender)))) %>%
  mutate(cgender_link = scale(gender_link)) %>%
  mutate(cgender_total = scale(gender_total))
adoptions_model <- lmer(resid_rt~ctrial_congruency*ctrial_gender*cgender_total + (1|workerid) + (1|lexeme) + (1|name),data = adoptions_only)
boundary (singular) fit: see ?isSingular
summary(adoptions_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: resid_rt ~ ctrial_congruency * ctrial_gender * cgender_total +  
    (1 | workerid) + (1 | lexeme) + (1 | name)
   Data: adoptions_only

REML criterion at convergence: 908.1

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.5128 -0.6018 -0.1059  0.5109  7.0153 

Random effects:
 Groups   Name        Variance Std.Dev.
 workerid (Intercept) 0.05710  0.2390  
 name     (Intercept) 0.00000  0.0000  
 lexeme   (Intercept) 0.02727  0.1651  
 Residual             0.10582  0.3253  
Number of obs: 1021, groups:  workerid, 175; name, 24; lexeme, 6

Fixed effects:
                                               Estimate Std. Error        df t value Pr(>|t|)   
(Intercept)                                     0.02989    0.07054   5.72225   0.424  0.68722   
ctrial_congruency                              -0.02857    0.02142 886.60879  -1.334  0.18270   
ctrial_gender                                  -0.01961    0.02153 892.34158  -0.911  0.36254   
cgender_total                                   0.05990    0.02075 171.22047   2.887  0.00439 **
ctrial_congruency:ctrial_gender                -0.01332    0.04317 892.38092  -0.309  0.75775   
ctrial_congruency:cgender_total                -0.01599    0.02131 877.46721  -0.750  0.45331   
ctrial_gender:cgender_total                     0.00566    0.02149 885.47768   0.263  0.79233   
ctrial_congruency:ctrial_gender:cgender_total   0.02592    0.04296 881.94051   0.603  0.54650   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                 (Intr) ctrl_c ctrl_g cgndr_ ctrl_cngrncy:ct_ ctrl_cngrncy:cg_ ctrl_g:_
ctrl_cngrnc       0.000                                                                
ctrial_gndr       0.000  0.026                                                         
cgender_ttl      -0.002 -0.007  0.004                                                  
ctrl_cngrncy:ct_  0.003 -0.003  0.006  0.002                                           
ctrl_cngrncy:cg_ -0.002 -0.017  0.005 -0.039  0.020                                    
ctrl_gndr:_       0.001  0.005  0.000  0.000 -0.002            0.022                   
ctrl_cn:_:_       0.001  0.019  0.000  0.011 -0.002           -0.002           -0.068  
optimizer (nloptwrap) convergence code: 0 (OK)
boundary (singular) fit: see ?isSingular

6.1 Full Model

all_data <- all_data %>%
  mutate(ctrial_congruency = as.numeric(as.factor(trial_congruency))-mean(as.numeric(as.factor(trial_congruency)))) %>%
  mutate(ctrial_gender = as.numeric(as.factor(trial_gender))-mean(as.numeric(as.factor(trial_gender)))) %>%
  mutate(cgender_link = scale(gender_link)) %>%
  mutate(cgender_total = scale(gender_total)) %>%
  mutate(cmorph_type = as.numeric(as.factor(morph_type))-mean(as.numeric(as.factor(morph_type))))
complex_model <- lmer(resid_rt~ctrial_congruency*ctrial_gender*cgender_total + (1|workerid) + (1|lexeme),data = all_data)
summary(complex_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: resid_rt ~ ctrial_congruency * ctrial_gender * cgender_total +  
    (1 | workerid) + (1 | lexeme)
   Data: all_data

REML criterion at convergence: 2471

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.6906 -0.6269 -0.1267  0.4992  7.6516 

Random effects:
 Groups   Name        Variance Std.Dev.
 workerid (Intercept) 0.06669  0.2582  
 lexeme   (Intercept) 0.01412  0.1188  
 Residual             0.10240  0.3200  
Number of obs: 3413, groups:  workerid, 175; lexeme, 20

Fixed effects:
                                                Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)                                    1.959e-04  3.342e-02  4.231e+01   0.006  0.99535    
ctrial_congruency                              5.729e-02  1.098e-02  3.214e+03   5.218 1.92e-07 ***
ctrial_gender                                  1.042e-02  1.098e-02  3.215e+03   0.949  0.34267    
cgender_total                                  5.580e-02  2.027e-02  1.730e+02   2.753  0.00654 ** 
ctrial_congruency:ctrial_gender               -2.174e-02  2.198e-02  3.215e+03  -0.989  0.32270    
ctrial_congruency:cgender_total                5.421e-03  1.098e-02  3.214e+03   0.494  0.62152    
ctrial_gender:cgender_total                   -1.135e-02  1.100e-02  3.215e+03  -1.032  0.30229    
ctrial_congruency:ctrial_gender:cgender_total -8.751e-03  2.199e-02  3.215e+03  -0.398  0.69065    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                 (Intr) ctrl_c ctrl_g cgndr_ ctrl_cngrncy:ct_ ctrl_cngrncy:cg_ ctrl_g:_
ctrl_cngrnc       0.000                                                                
ctrial_gndr       0.000 -0.002                                                         
cgender_ttl      -0.001  0.001  0.000                                                  
ctrl_cngrncy:ct_  0.000  0.000  0.002  0.000                                           
ctrl_cngrncy:cg_  0.001 -0.001 -0.001  0.001  0.001                                    
ctrl_gndr:_       0.000  0.000  0.001  0.001  0.003           -0.002                   
ctrl_cn:_:_       0.000  0.002  0.003  0.000 -0.001            0.002            0.004  

6.2 Gender Total

ideology_model <- lmer(resid_rt~ctrial_congruency*ctrial_gender*cgender_link + (1|workerid) + (1|lexeme), data=all_data)
summary(ideology_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: resid_rt ~ ctrial_congruency * ctrial_gender * cgender_link +  
    (1 | workerid) + (1 | lexeme)
   Data: all_data

REML criterion at convergence: 2469.7

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.6650 -0.6231 -0.1237  0.4958  7.6201 

Random effects:
 Groups   Name        Variance Std.Dev.
 workerid (Intercept) 0.06572  0.2564  
 lexeme   (Intercept) 0.01414  0.1189  
 Residual             0.10244  0.3201  
Number of obs: 3413, groups:  workerid, 175; lexeme, 20

Fixed effects:
                                               Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)                                   1.834e-04  3.336e-02  4.188e+01   0.005  0.99564    
ctrial_congruency                             5.731e-02  1.098e-02  3.215e+03   5.219 1.91e-07 ***
ctrial_gender                                 1.045e-02  1.098e-02  3.215e+03   0.952  0.34129    
cgender_link                                  6.373e-02  2.008e-02  1.732e+02   3.174  0.00178 ** 
ctrial_congruency:ctrial_gender              -2.168e-02  2.198e-02  3.215e+03  -0.986  0.32403    
ctrial_congruency:cgender_link                5.535e-03  1.098e-02  3.215e+03   0.504  0.61433    
ctrial_gender:cgender_link                   -4.886e-03  1.100e-02  3.215e+03  -0.444  0.65691    
ctrial_congruency:ctrial_gender:cgender_link -1.102e-03  2.199e-02  3.215e+03  -0.050  0.96004    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
                 (Intr) ctrl_c ctrl_g cgndr_ ctrl_cngrncy:ct_ ctrl_cngrncy:cg_ ctrl_g:_
ctrl_cngrnc       0.000                                                                
ctrial_gndr       0.000 -0.002                                                         
cgender_lnk      -0.001  0.001  0.001                                                  
ctrl_cngrncy:ct_  0.000  0.000  0.002  0.000                                           
ctrl_cngrncy:cg_  0.001 -0.001  0.001  0.002  0.002                                    
ctrl_gndr:_       0.000  0.001  0.000  0.001  0.004            0.000                   
ctrl_cn:_:_       0.000  0.003  0.004  0.000 -0.001            0.003            0.009  
summary(gender_model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: resid_rt ~ ctrial_congruency * ctrial_gender * cgender + (1 |      workerid) + (1 | lexeme)
   Data: all_data

REML criterion at convergence: 2474

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.6179 -0.6286 -0.1283  0.4998  7.6343 

Random effects:
 Groups   Name        Variance Std.Dev.
 workerid (Intercept) 0.06980  0.2642  
 lexeme   (Intercept) 0.01415  0.1190  
 Residual             0.10242  0.3200  
Number of obs: 3413, groups:  workerid, 175; lexeme, 20

Fixed effects:
                                          Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)                              2.636e-04  3.371e-02  4.347e+01   0.008    0.994    
ctrial_congruency                        5.727e-02  1.098e-02  3.214e+03   5.215 1.95e-07 ***
ctrial_gender                            1.040e-02  1.098e-02  3.215e+03   0.947    0.344    
cgender                                  1.202e-02  3.832e-02  1.729e+02   0.314    0.754    
ctrial_congruency:ctrial_gender         -2.166e-02  2.198e-02  3.215e+03  -0.986    0.324    
ctrial_congruency:cgender                5.750e-05  2.032e-02  3.214e+03   0.003    0.998    
ctrial_gender:cgender                   -9.633e-03  2.036e-02  3.216e+03  -0.473    0.636    
ctrial_congruency:ctrial_gender:cgender  3.230e-02  4.068e-02  3.215e+03   0.794    0.427    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) ctrl_c ctrl_g cgendr ctr_:_ ctrl_c: ctrl_g:
ctrl_cngrnc  0.000                                            
ctrial_gndr  0.000 -0.002                                     
cgender      0.000 -0.001  0.000                              
ctrl_cngr:_  0.000  0.000  0.002  0.000                       
ctrl_cngrn: -0.001  0.002 -0.001 -0.001 -0.002                
ctrl_gndr:c  0.000  0.000  0.001  0.001 -0.002 -0.005         
ctrl_cng:_:  0.000 -0.001 -0.004 -0.001  0.000  0.004  -0.004 

7 Comments

all_data %>%
  group_by(workerid,poli_party) %>%
  summarise(comments = paste(unique(subject_information.comments))) %>%
  select(poli_party,comments)
`summarise()` has grouped output by 'workerid'. You can override using the `.groups` argument.
Adding missing grouping variables: `workerid`

8 Testing Grounds

8.1 Checking the times

new_toy <- read.csv('maze_task_1-merged.csv') %>%
  filter(trial_id!= 'example') %>%
  filter(response_correct != 0) %>%
  mutate(trial_gender = ifelse(condition=='neutral_female' | condition == 'congruent_female','female','male')) %>%
  mutate(trial_congruency = ifelse(condition=='congruent_male' | condition == 'congruent_female','congruent','neutral'))
new_toy %>%
  group_by(word_idx,trial_gender) %>%
  summarize(MeanRT = mean(rt)) %>%
  ggplot(aes(x=word_idx, y=log(MeanRT), color=trial_gender)) + 
  geom_line() + 
  geom_point()
`summarise()` has grouped output by 'word_idx'. You can override using the `.groups` argument.

new_toy %>%
  group_by(word_idx,trial_gender) %>%
  summarize(MeanRT = mean(rt)) %>%
  ggplot(aes(x=word_idx, y=MeanRT, color=trial_gender)) + 
  geom_line() + 
  geom_point()
`summarise()` has grouped output by 'word_idx'. You can override using the `.groups` argument.

all_data %>%
  filter(!is.na(poli_party)) %>%
  group_by(poli_party) %>%
  summarize(MeanGenderTotal = mean(gender_total)) %>%
  ggplot(aes(x=poli_party, y=MeanGenderTotal)) + 
  geom_bar(stat = 'identity') + 
  theme_minimal() + 
  labs(y="Mean Gender Total", x="Political Party")

all_data %>%
  filter(!is.na(subject_information.gender)) %>%
  filter(subject_information.gender != '') %>%
  group_by(subject_information.gender) %>%
  summarize(MeanGenderTotal = mean(gender_total)) %>%
  ggplot(aes(x=subject_information.gender, y=MeanGenderTotal)) + 
  geom_bar(stat = 'identity') + 
  theme_minimal() + 
  labs(y="Mean Gender Total", x="Participant Gender")

Rscript merge_results.R maze_task_1-merged.csv dems maze_task_2-merged.csv reps

all_data %>%
  group_by(condition,trial_gender) %>%
  filter(trial_no < 11) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender)) + 
  geom_point(size=3) + 
  geom_jitter(data = agg_speaker_mean_con, aes(y=MeanRT),alpha=.1,color='darkred') + 
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  scale_color_manual(values = inauguration_2021) + 
  theme_minimal()
`summarise()` has grouped output by 'condition'. You can override using the `.groups` argument.

8.2 The Flight Attendant Question

all_data %>%
  filter(lexeme == "flight attendant") %>%
  filter(!is.na(poli_party)) %>%
  group_by(condition,trial_gender,trial_congruency,poli_party) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender,shape=trial_congruency)) + 
  geom_point(size=3) +
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  theme(axis.text.x = element_text(angle = 45, vjust = .7, hjust=.7)) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~poli_party)
`summarise()` has grouped output by 'condition', 'trial_gender', 'trial_congruency'. You can override using the `.groups` argument.

all_data %>%
  filter(lexeme == "flight attendant") %>%
  filter(!is.na(subject_information.gender)) %>%
  group_by(condition,trial_gender,trial_congruency,subject_information.gender) %>%
  summarize(MeanRT = mean(resid_rt), CI.Low = ci.low(resid_rt), CI.High = ci.high(resid_rt)) %>%
  mutate(YMin = MeanRT - CI.Low, YMax = MeanRT + CI.High) %>%
  ggplot(aes(x=condition,y=MeanRT,color=trial_gender,shape=trial_congruency)) + 
  geom_point(size=3) +
  geom_errorbar(aes(ymin=YMin,ymax=YMax), width=.25) + 
  theme(axis.text.x = element_text(angle = 45, vjust = .7, hjust=.7)) + 
  scale_color_manual(values = inauguration_2021) + 
  facet_wrap(~subject_information.gender)
`summarise()` has grouped output by 'condition', 'trial_gender', 'trial_congruency'. You can override using the `.groups` argument.


  1. Part of this experiment and analysis was also carried out as part of my class project in Stanford’s LINGUIST 245B ‘Methods in Psycholinguistics’ class, taught by Judith Degen.↩︎

  2. This amounts to an hourly rate of $20.73. We originally anticipated that participants would take an average of 7 minutes to complete the experiment, and set the base pay at $15 an hour.↩︎

LS0tCnRpdGxlOiAiR2VuZGVyIElkZW9sb2dpZXMgYW5kIExhbmd1YWdlIFByb2Nlc3Npbmc6IEEgU2VsZi1QYWNlZCBSZWFkaW5nIFRpbWUgU3R1ZHkiCmF1dGhvcjogIkIuIFBhcGluZWF1IgpkYXRlOiAiMjAyMSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IG5vCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdGhlbWU6IGpvdXJuYWwKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCiMgSW50cm9kdWN0aW9uClRoaXMgZG9jdW1lbnQgY29udGFpbnMgdGhlIHJlc3VsdHMgYW5kIGFuYWx5c2lzIG9mIG15IHNlY29uZCBleHBlcmltZW50IGZvciBteSBmaXJzdCBRdWFsaWZ5aW5nIFBhcGVyIHRvd2FyZHMgdGhlIFBoRCBpbiBMaW5ndWlzdGljcyBhdCBTdGFuZm9yZCBVbml2ZXJzaXR5XltQYXJ0IG9mIHRoaXMgZXhwZXJpbWVudCBhbmQgYW5hbHlzaXMgd2FzIGFsc28gY2FycmllZCBvdXQgYXMgcGFydCBvZiBteSBjbGFzcyBwcm9qZWN0IGluIFN0YW5mb3JkJ3MgTElOR1VJU1QgMjQ1QiAnTWV0aG9kcyBpbiBQc3ljaG9saW5ndWlzdGljcycgY2xhc3MsIHRhdWdodCBieSBKdWRpdGggRGVnZW4uXS4gCgojIE1ldGhvZHMKIyMgVGhlIEV4cGVyaW1lbnQKVGhlIGV4cGVyaW1lbnQgYW5hbHl6ZWQgaGVyZWluIHdhcyBhbiBvbmxpbmUgbWF6ZSB0YXNrIHN0dWR5LCB3aGVyZWluIHBhcnRpY2lwYW50cyByZWFkIGEgc2VudGVuY2Ugc3VjaCBhcyAiRGF2aWQgaXMgYSBjb25ncmVzc3BlcnNvbiBmcm9tIFZpcmdpbmlhLiBIZSBsaWtlcyBjeWNsaW5nLiIgRm9yIGVhY2ggb2YgdGhlIDIwIGNyaXRpY2FsIGl0ZW1zLCBwYXJ0aWNpcGFudHMgd2VyZSByYW5kb21seSBhc3NpZ25lZCB0byBvbmUgb2YgZm91ciBjb25kaXRpb25zLCB0aGUgY3JpdGljYWwgcmVnaW9ucyBvZiB3aGljaCBhcmUgZW51bWVyYXRlZCBhbmQgZXhlbXBsaWZpZWQgaGVyZToKCjxvbD4KICA8bGk+TWFsZS1jb25ncnVlbnQ6IDxpPkRhdmlkIGlzIGEgY29uZ3Jlc3NtYW48L2k+PC9saT4KICA8bGk+TWFsZS1uZXV0cmFsOiA8aT5EYXZpZCBpcyBhIGNvbmdyZXNzcGVyc29uPC9pPjwvbGk+CiAgPGxpPkZlbWFsZS1jb25ncnVlbnQ6IDxpPlNhbGx5IGlzIGEgY29uZ3Jlc3N3b21hbjwvaT48L2xpPgogIDxsaT5GZW1hbGUtbmV1dHJhbDogPGk+U2FsbHkgaXMgYSBjb25ncmVzc3BlcnNvbjwvaT48L2xpPgo8L29sPgoKUGFydGljaXBhbnRzIHByb2NlZWRlZCB0aHJvdWdoIHRoZSBzZW50ZW5jZXMgYnkgcHJlc3NpbmcgYSBrZXlib2FyZCBrZXkgd2hpY2ggY29ycmVzcG9uZGVkIHRvIHRoZSBncmFtbWF0aWNhbCBjb250aW51YXRpb24gb2YgdGhlIHNlbnRlbmNlLCBhbmQgcmVhZGluZyBwYWlyIG9mIGdyYW1tYXRpY2FsIGFuZCBkaXN0cmFjdG9yIGl0ZW1zIGF0IGEgdGltZS4gVGhleSB3ZXJlIHRoZW4gYXNrZWQgYXR0ZW50aW9uIGNoZWNrIHF1ZXN0aW9ucyBhdCB0aGUgZW5kIG9mIGVhY2ggc2VudGVuY2U7IGF0dGVudGlvbiBjaGVjayBxdWVzdGlvbnMgbmV2ZXIgZXhwbGljaXRseSBpbnZva2VkIGdlbmRlci4gUmF0aGVyLCB0aGV5IGFza2VkIGFib3V0IHRoZSBjaGFyYWN0ZXIncyBob21lIHN0YXRlcy4gRm9yIGEgaGFuZHMtb24gbG9vayBhdCB0aGUgZXhwZXJpbWVudCwgeW91IGNhbiBjbGljayA8YSBocmVmPSJodHRwczovL2JyYW5wYXAuZ2l0aHViLmlvL2dlbmRlcl9wcm9jZXNzaW5nL2V4cGVyaW1lbnRzLzJfTWF6ZV9OZXV0cmFsaXR5L2V4cGVyaW1lbnQvZXhwZXJpbWVudC5odG1sIj4gaGVyZTwvYT4gdG8gZ28gdG8gdGhlIHNhbWUgd2VicGFnZSBwYXJ0aWNwYW50cyB3ZXJlIGRpcmVjdGVkIHRvIGZvciB0aGUgdGFzay4KCiMjIFBhcnRpY2lwYW50cyAKV2Ugb3JpZ2luYWxseSByYW4gdGhlIGV4cGVyaW1lbnQgb24gMjAwIHBhcnRpY2lwYW50cywgcmVjcnVpdGVkIHRocm91Z2ggdGhlIG9ubGluZSBwYXJ0aWNpcGFudCByZWNydWl0bWVudCBwbGF0Zm9ybSA8YSBocmVmPSJodHRwczovL3d3dy5wcm9saWZpYy5jbyI+UHJvbGlmaWM8L2E+LiBUaGUgbWVhbiB0aW1lIG9mIHRoZSBleHBlcmltZW50IHdhcyA1LjM5IG1pbnV0ZXMsIGFuZCBwYXJ0aWNpcGFudHMgd2VyZSBwYWlkICQxLjc1IGZvciB0aGVpciBwYXJ0aWNpcGF0aW9uXltUaGlzIGFtb3VudHMgdG8gYW4gaG91cmx5IHJhdGUgb2YgXCQyMC43My4gV2Ugb3JpZ2luYWxseSBhbnRpY2lwYXRlZCB0aGF0IHBhcnRpY2lwYW50cyB3b3VsZCB0YWtlIGFuIGF2ZXJhZ2Ugb2YgNyBtaW51dGVzIHRvIGNvbXBsZXRlIHRoZSBleHBlcmltZW50LCBhbmQgc2V0IHRoZSBiYXNlIHBheSBhdCBcJDE1IGFuIGhvdXIuXS4gVGhlIG9ubHkgcmVzdHJpY3Rpb25zIHBsYWNlZCBvbiBwYXJ0aWNpcGFudHMgd2VyZSB0aGF0IHRoZXk6Cgo8b2w+CiAgPGxpPldlcmUgYm9ybiBpbiB0aGUgVW5pdGVkIFN0YXRlczwvbGk+CiAgPGxpPkxpdmVkIGluIHRoZSBVbml0ZWQgU3RhdGVzIGF0IHRoZSB0aW1lIG9mIHBhcnRpY2lwYXRpb248L2xpPgogIDxsaT5TcG9rZSBFbmdsaXNoIGFzIGEgZmlyc3QgbGFuZ3VhZ2U8L2xpPgogIDxsaT5IYWQgbm90IHBhcnRpY2lwYXRlZCBpbiB0aGUgbm9ybWluZyBzdHVkeSBmb3IgdGhlIHN0aW11bGk8L2xpPgo8L29sPgoKVGhlc2UgcmVxdWlyZW1lbnRzIHdlcmUgaW1wbGVtZW50ZWQgaW4gb3JkZXIgdG8gYXNzdXJlIHRoYXQgc3BlYWtlcnMgY2FtZSBmcm9tIGF0IGxlYXN0IHNvbWV3aGF0IHNpbWlsYXIgbGluZ3Vpc3RpYyBiYWNrZ3JvdW5kcywgYXMgY2VydGFpbiBsZXhpY2FsIGl0ZW1zIGluIHRoZSBzdHVkeSAoc3VjaCBhcyA8aT5jb25ncmVzc3BlcnNvbjwvaT4pIGFyZSBxdWl0ZSBsb2NhbGl6ZWQgdG8gdGhlIFVuaXRlZCBTdGF0ZXMuCgpBZnRlciB0aGlzIGluaXRpYWwgcnVuIG9mIHRoZSBleHBlcmltZW50LCB3ZSBmb3VuZCB0aGF0IHRoZXJlIHdhcyBhIGRlYXJ0aCBvZiBjb25zZXJ2YXRpdmUgb3IgUmVwdWJsaWNhbi1hbGlnbmVkIHBhcnRpY2lwYW50cy4gQXMgYSByZXN1bHQsIHdlIHJhbiB0aGUgZXhwZXJpbWVudCBhZ2FpbiwgdGhpcyB0aW1lIG9uIDk4IHNlbGYtaWRlbnRpZmllZCBSZXB1YmxpY2Fucy4gVGhpcyB3YXMgYWNoaWV2ZWQgYnkgYWRkaW5nIGEgZmlsdGVyIG9uIFByb2xpZmljIHNvIHRoYXQgb25seSBSZXB1YmxpY2FuLWlkZW50aWZpZWQgaW5kaXZpZHVhbHMgY291bGQgc2VlIHRoZSB0YXNrLiBUaGUgcmVzdCBvZiB0aGUgZXhwZXJpbWVudCwgaW5jbHVkaW5nIHBheW1lbnQsIHdhcyBleGFjdGx5IHRoZSBzYW1lLCBleGNlcHQgdGhhdCBhbiBhZGRpdGlvbmFsIGRpc2NsYWltZXIgdGhhdCBwYXJ0aWNpcGFudHMgY291bGQgbm90IHVzZSB0aGUgRmlyZUZveCBicm93c2VyIGV4cGVyaW1lbnQsIGFmdGVyIHRoZSBmaXJzdCBydW4gcmV2ZWFsZWQgYW4gaW5jb21wYXRpYmlsaXR5IGJldHdlZW4gSmF2YVNjcmlwdCBhbmQgRmlyZUZveC4gVGhlIHR3byBydW5zIG9mIHRoZSBleHBlcmltZW50IGFtb3VudGVkIGluIGEgdG90YWwgb2YgMjk4IHBhcnRpY2lwYW50cyB3aG8gY29tcGxldGVkIHRoZSB0YXNrLgoKIyBQcmVwcGluZyB0aGUgRGF0YQpCZWZvcmUgd2UgY2FuIGRvIG11Y2ggb2YgYW55dGhpbmcgd2l0aCB0aGUgZGF0YSwgd2UgbmVlZCB0byBtYWtlIHN1cmUgaXQncyB1c2FibGUhIFRoaXMgbWVhbnMgZmlsdGVyaW5nIG91dCBhbGwgdW5pbXBvcnRhbnQgb3IgZXh0cmFuZW91cyB0cmlhbHMsIHJ1bm5pbmcgZXhjbHVzaW9uIGNyaXRlcmlhLCBhbmQgYWRkaW5nIGFkZGl0aW9uYWwgdHJpYWwgYW5kIGl0ZW0tbGV2ZWwgZGF0YSB0aGF0IHdpbGwgYmUgbmVjZXNzYXJ5IGxhdGVyIGluIHRoZSBhbmFseXNpcy4KCiMjIFBhY2thZ2VzCkZvciB0aGlzIGFuYWx5c2lzLCB3ZSByZXF1aXJlIHRoZSBmb2xsb3dpbmcgcGFja2FnZXM6CgpgYGB7ciBlY2hvPVRSVUV9CmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkodGlkeXZlcnNlKSAKbGlicmFyeShsbWU0KSAKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGxhbmd1YWdlUikKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShyZXNoYXBlMikKCnNvdXJjZSgiaGVscGVycy5SIikKYGBgCgpgYGB7cn0KdGhlbWVfc2V0KHRoZW1lX21pbmltYWwoKSkKYGBgCgoKIyMgUmVhZGluZyBpbiB0aGUgRGF0YQpJbiB0aGUgZmlyc3QgaW5zdGFuY2UsIHdlIG5lZWQgdG8gcmVhZCBpbiB0aGUgZGF0YSwgd2hpY2ggaGFzIGJlZW4gcHJlLW1lcmdlZCBmcm9tIGJvdGggcnVucyBvZiB0aGUgZXhwZXJpbWVudC4gV2Ugd2lsbCBhbHNvIGluIHRoaXMgY2h1bmsgZmlsdGVyIG91dCBhbGwgb2YgdGhlIGV4YW1wbGUgdHJpYWxzLCBhcyB3ZWxsIGFzIGFsbCB0aGUgZGF0YSBwb2ludHMgdGhhdCBhcmUgZnJvbSBub24tY3JpdGljYWwgdHJpYWxzLiAKCmBgYHtyfQphbGxfZGF0YSA8LSByZWFkLmNzdignbWVyZ2VkX2FsbC5jc3YnKSAlPiUKICBmaWx0ZXIodHJpYWxfaWQhPSAnZXhhbXBsZScpICU+JQogIGZpbHRlcihyZWdpb249PSdjcml0aWNhbCcpCmBgYAoKIyMgUnVubmluZyBFeGNsdXNpb24gQ3JpdGVyaWEKTm93LCB3ZSB3YW50IHRvIGV4Y2x1ZGUgYW55IHBhcnRpY2lwYW50cyB3aG8gZmFpbGVkIHRvIGFuc3dlciBhdCBsZWFzdCA4MCUgb2YgdGhlIGF0dGVudGlvbiBjaGVjayBxdWVzdGlvbnMgY29ycmVjdGx5LiBXZSBkbyB0aGlzIGJ5IGNyZWF0aW5nIGEgbGlzdCBvZiBhbGwgcGFydGljaXBhbnRzIHdobyBzY29yZWQgbGVzcyB0aGFuIDgwJSBvbiB0aGVzZSBjaGVja3MsIGFuZCB0aGVuIGNyb3NzLXJlZmVyZW5jaW5nIHRoaXMgbGlzdCB3aXRoIGFsbCBkYXRhIHBvaW50cywgcmVtb3ZpbmcgYW55IGRhdGEgcG9pbnRzIHdob3NlIHBhcnRpY2lwYW50cyB3ZXJlIGluIHRoZSBleGNsdXNpb24gbGlzdC4gCgpgYGB7cn0KZXhjbHVzaW9uIDwtIGFsbF9kYXRhICU+JSBncm91cF9ieSh3b3JrZXJpZCkgJT4lCiAgc3VtbWFyaXNlKGFjY3VyYWN5ID0gbWVhbihyZXNwb25zZV9jb3JyZWN0KSkgJT4lCiAgbXV0YXRlKGV4Y2x1ZGUgPSBpZmVsc2UoYWNjdXJhY3kgPCAwLjgwLCdZZXMnLCdObycpKSAlPiUgCiAgZmlsdGVyKGV4Y2x1ZGUgPT0gJ1llcycpCgphbGxfZGF0YSA8LSBhbGxfZGF0YVshKGFsbF9kYXRhJHdvcmtlcmlkICVpbiUgZXhjbHVzaW9uJHdvcmtlcmlkKSxdICU+JQogIGZpbHRlcihydCAhPSdudWxsJykKYGBgCgpXZSBhbHNvIHdhbnQgdG8gZmlsdGVyIG91dCBhbGwgdHJpYWxzIGluIHdoaWNoIHRoZSByZWFkaW5nIHRpbWUgZm9yIHRoZSBjcml0aWNhbCBpdGVtIHdhcyBtb3JlIHRoYW4gMi41IHN0YW5kYXJkIGRldmlhdGlvbnMgZnJvbSB0aGUgbWVhbiByZWFkaW5nIHRpbWUgb24gdGhhdCBsZXhpY2FsIGl0ZW0gYWNyb3NzIGFsbCBwYXJ0aWNpcGFudHMuIAoKCgoKYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkodHJpYWxfaWQpICU+JQogIG11dGF0ZShpZF9tZWFuID0gbWVhbihsb2cocnQpKSkgJT4lCiAgbXV0YXRlKGV4Y2x1c2lvbiA9IChsb2cocnQpIDwgbWVhbihsb2cocnQpKSAtIDIqc2QobG9nKHJ0KSl8KGxvZyhydCkgPiBtZWFuKGxvZyhydCkpICsgMipzZChsb2cocnQpKSkpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKGV4Y2x1c2lvbj09RkFMU0UpCgoKClRoaXMgcmVzdWx0cyBpbiAyMzggdHJpYWxzIGJlaW5nIHJlbW92ZWQgZnJvbSB0aGUgNTU4MCB3ZSBnb3QgYWZ0ZXIgdGhlIGJ5LXBhcnRpY2lwYW50IGV4Y2x1c2lvbnMuIFdlIG5vdyBoYXZlIDUzNDIgdHJpYWxzIHdlIGNhbiB1c2UgZm9yIGFuYWx5c2lzLgoKIyMgQWRkaW5nIGluIEFkZGl0aW9uYWwgSW1wb3J0YW50IFRyaWFsIEluZm9ybWF0aW9uIHsudGFic2V0fQpOb3cgdGhhdCB3ZSBoYXZlIG9ubHkgdGhlIHJvd3Mgd2Ugd2FudCwgbGV0J3MgYWRkIHNvbWUgbmV3IGNvbHVtbnMsIHdoaWNoIHdpbGwgY29udGFpbiBpbXBvcnRhbnQgaW5mb3JtYXRpb24gZm9yIGVhY2ggZGF0YSBwb2ludC4gSGVyZSwgd2Ugd2lsbCBiZSBhZGRpbmc6CgotIEdlbmRlciBJZGVvbG9neSBTdWJzY29yZXMKLSBUcmlhbCBHZW5kZXJzCi0gVHJpYWwgTW9ycGhvbG9neSBUeXBlcwotIENyaXRpY2FsIEl0ZW0gTGVuZ3RoICYgTGVuZ3RoLUNvbnRyb2xsZWQgUmVzaWR1YWxzCi0gVHJpYWwgQ29uZ3J1ZW5jeSAKLSBQYXJ0aXBhbnQgUG9saXRpY2FsIEFmZmlsaWF0aW9uCgpJZGVhbGx5LCBJIHdvdWxkJ3ZlIGFkZGVkIGFsbCBvZiB0aGVzZSBidXQgdGhlIGZpcnN0IHdoZW4gSSBhY3R1YWxseSBjcmVhdGVkIHRoZSBzdGltdWxpIGFuZCBsb2dnZWQgcmVzcG9uc2VzLCBidXQgSSBmb3Jnb3QgdG8hIEx1Y2tpbHksIFIgYWxsb3dzIHVzIHRvIGRvIHRoaXMgcG9zdC1ob2MgZmFpcmx5IHN0cmFpZ2h0Zm9yd2FyZGx5Li4uIHdoaWNoIGlzIGdvb2QsIHNpbmNlIHRoZXNlIGZlYXR1cmVzIHdpbGwgYmUgY3JpdGljYWwgaW4gb3VyIGRhdGEgdmlzdWFsaXphdGlvbiBhbmQgYW5hbHlzaXMuPGJyPgo8YnI+CgojIyMgRGVmaW5pbmcgR2VuZGVyIFN1YnNjb3Jlcwo8YnI+ClRoZSBxdWVzdGlvbiB1bmRlciBpbnZlc3RpZ2F0aW9uIGhlcmUgaXMgd2hldGhlciBvciBub3QgaW5kaXZpZHVhbHMnIGNvbmNlcHRpb25zIG9mIGdlbmRlciBhZmZlY3QgaG93IHRoZXkgcHJvY2VzcyAgZ2VuZGVyZWQgYW5kIGdlbmRlci1uZXV0cmFsIGZvcm1zIG9mIEVuZ2xpc2ggcGVyc29uYWwgYW5kIHByb2Zlc3Npb25hbCB0aXRsZXMuIDxicj4KPGJyPgpJbiBvcmRlciB0byBleGFtaW5lIHRoaXMsIHdlIG5lZWQgdG8gcXVhbmlmeSBwYXJ0aWNpcGFudHMnIGlkZW9sb2dpY2FsIHZpZXdzISBIZXJlIHdlIGhhdmUgYWRvcHRlZCB0aGUgMTMtaXRlbSBTb2NpYWwgUm9sZXMgUXVlc3Rpb25uYWlyZSBwdXQgZm9ydGggaW4gQmFiZXIgJiBUdWNrZXIgKDIwMDYpLiBRdWVzdGlvbnMgMS01IGNvcnJlbGF0ZSB0byB0aGUgPGk+J0dlbmRlciBUcmFuc2NlbmRlbnQnPC9pPiBzdWJzY2FsZSwgYW5kIHF1ZXN0aW9ucyA2LTEzIGNvcnJlc3BvbmQgdG8gdGhlIDxpPidHZW5kZXIgTGlua2VkJzwvaT4gc3Vic2NhbGUuIEVhY2ggaXRlbSBpcyBzY29yZWQgb24gYSBzY2FsZSBvZiAwLTEwMC4gU28sIHRoZSBmaXJzdCB0aGluZyB3ZSB3YW50IHRvIGRvIGlzIG1ha2UgdHdvIGxpc3RzIG9mIGNvbHVtbnMgd2hpY2ggY29ycmVzcG9uZCB0byB0aGVzZSB0d28gc3Vic2NhbGVzLCBzaW5jZSB0aGUgcXVlc3Rpb25zIGFyZSBzdG9yZWQgaW5kaXZpZHVhbGx5IGluIHRoZSBkYXRhOgoKYGBge3J9CmdlbmRlcl90cmFuc2NlbmRlbmNlX2NvbHMgPC0gYygnc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXJfcTEnLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xMicsJ3N1YmplY3RfaW5mb3JtYXRpb24uZ2VuZGVyX3EzJywnc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXJfcTQnLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xNScpCgpnZW5kZXJfbGlua2VkX2NvbHMgPC0gYygnc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXJfcTYnLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xNycsJ3N1YmplY3RfaW5mb3JtYXRpb24uZ2VuZGVyX3E4Jywnc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXJfcTknLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xMTAnLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xMTEnLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xMTInLCdzdWJqZWN0X2luZm9ybWF0aW9uLmdlbmRlcl9xMTMnKQpgYGAKPGJyPgpOb3cgd2UgY2FuIHVzZSB0aGUgbXV0YXRlKCkgbWV0aG9kIG9uIDxiPmFsbF9kYXRhPC9iPiB0byBhZGQgdHdvIG5ldyBjb2x1bW5zLCBvbmUgZm9yIGVhY2ggc3Vic2NhbGUuIFdlIHRlbGwgUiB0byB0YWtlIHRoZSBtZWFucyBvZiB0aGUgc3BlY2lmaWVkIGNvbHVtbnMgaW4gW2NvbHVtbl9uYW1lc10gb2YgPGI+YWxsX2RhdGE8L2I+IGZvciBlYWNoIGluZGl2aWR1YWwgcm93OiByb3dNZWFucyhhbGxfZGF0YVtjb2x1bW5fbmFtZXNdKS4gV2UgYWxzbyBoYXZlIHRvIHN1YnRyYWN0IHRoaXMgbWVhbiBmcm9tIDEwMCBpbiB0aGUgY2FzZSBvZiB0aGUgPGk+J0dlbmRlciBUcmFuc2NlbmRlbnQnPC9pPiBzdWJzY2FsZSwgc2luY2UgaXQgaXMgaW52ZXJzZWx5IHNjb3JlZC4gRmluYWxseSwgd2UgY2FuIGNyZWF0ZSBhbiBhdmVyYWdlIHRvdGFsIHNjb3JlIHJlZ2FyZGxlc3Mgb2Ygc3Vic2NvcmVzLCBzaW1wbHkgYnkgbWVhbmluZyB0aGUgdHdvIHN1YnNjb3JlcyB3ZSBhbHJlYWR5IGhhdmUuCgpgYGB7cn0KYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKGdlbmRlcl90cmFucyA9IDEwMCAtIChyb3dNZWFucyhhbGxfZGF0YVtnZW5kZXJfdHJhbnNjZW5kZW5jZV9jb2xzXSkpKSAlPiUKICBtdXRhdGUoZ2VuZGVyX2xpbmsgPSByb3dNZWFucyhhbGxfZGF0YVtnZW5kZXJfbGlua2VkX2NvbHNdKSkgCgpnZW5kZXJfYWxsID0gYygnZ2VuZGVyX3RyYW5zJywnZ2VuZGVyX2xpbmsnKQoKYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKGdlbmRlcl90b3RhbCA9IHJvd01lYW5zKGFsbF9kYXRhW2dlbmRlcl9hbGxdKSkKYGBgCgoKIyMjIEFkZGluZyBHZW5kZXIKPGJyPgpXZSBhbHNvIHdhbnQgdG8gYWRkIHdoZXRoZXIgdGhlIHRyaWFsIGluY2x1ZGVkIGEgZmVtYWxlIG9yIG1hbGUgcmVmZXJlbnQgKGJ1dCBhbHNvLCBsaWtlLCBkZXN0cm95IHRoZSBiaW5hcnkhKS4gSW4gb3JkZXIgdG8gZG8gdGhpcywgd2UnbGwganVzdCBhZGQgYSA8Yj50cmlhbF9nZW5kZXI8L2I+IGNvbHVtbiB0aGF0IHNheXMgPGk+J2ZlbWFsZSc8L2k+IGlmIHRoZSBjb25kaXRpb24gd2FzIGVpdGhlciA8aT4nbmV1dHJhbF9mZW1hbGUnPC9pPiBvciA8aT4nY29uZ3J1ZW50X2ZlbWFsZSc8L2k+LiBPdGhlcndpc2UsIHdlIHdhbnQgdGhlIDxiPnRyaWFsX2dlbmRlcjwvYj4gdG8gc2F5IDxpPidtYWxlJzwvaT4uCgpgYGB7cn0KYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKHRyaWFsX2dlbmRlciA9IGlmZWxzZShjb25kaXRpb249PSduZXV0cmFsX2ZlbWFsZScgfCBjb25kaXRpb24gPT0gJ2NvbmdydWVudF9mZW1hbGUnLCdmZW1hbGUnLCdtYWxlJykpCgphbGxfZGF0YSAlPiUKICBzZWxlY3Qod29ya2VyaWQscnQsY29uZGl0aW9uLHRyaWFsX2lkLHRyaWFsX2dlbmRlcikKYGBgCgojIyMgQWRkaW5nIE1vcnBob2xvZ3kgVHlwZQo8YnI+Ck5vdyB3ZSB3YW50IHRvIGFkZCB3aGV0aGVyIG9yIG5vdCB0aGUgbGV4ZW1lJ3MgbmV1dHJhbCBmb3JtIGlzIGRldmVsb3BlZCBieSBjb21wb3VuZGluZyAoYXMgaW4gPGk+J2NvbmdyZXNzLXBlcnNvbic8L2k+KSBvciBieSB0aGUgYWRvcHRpb24gb2YgdGhlIG1hbGUgZm9ybSAoYXMgaW4gPGk+J2FjdG9yJzwvaT4gYmVpbmcgdXNlZCBtb3JlIGZvciBib3RoIG1lbiBhbmQgd29tZW4pLiBJbiB0aGlzIHN0dWR5LCB3ZSBvbmx5IGhhdmUgc2l4IGxleGVtZXMgb2YgdGhlIGxhdHRlciB0eXBlLCBzbyB3ZSdsbCBqdXN0IHRlbGwgUiB0byBhc3NpZ24gdGhvc2UgYSA8Yj5tb3JwaF90eXBlPC9iPiB2YWx1ZSBvZiA8aT4nYWRvcHRpb24nPC9pPiAoZm9yICdtYWxlIGFkb3B0aW9uJyksIGFuZCBhbGwgZWxzZSB3aWxsIGJlIGFzc2lnbmVkIGEgdmFsdWUgb2YgPGk+J2NvbXBvdW5kJzwvaT4uCgpgYGB7cn0KYWxsX2RhdGEgPC0gYWxsX2RhdGElPiUKICBtdXRhdGUobW9ycGhfdHlwZSA9IGlmZWxzZShsZXhlbWUhPSAnYWN0b3InICYgbGV4ZW1lIT0gJ2hvc3QnICYgbGV4ZW1lICE9J2h1bnRlcicgJiBsZXhlbWUhPSAndmlsbGFpbicgJiBsZXhlbWUhPSAnaGVpcicgJiBsZXhlbWUhPSAnaGVybycsJ2NvbXBvdW5kJywnYWRvcHRpb24nKSkKCmFsbF9kYXRhICU+JQogIHNlbGVjdChydCxsZXhlbWUsbW9ycGhfdHlwZSkKYGBgCgoKIyMjIEFkZGluZyBGb3JtIExlbmd0aCAmIExlbmd0aC1Db250cm9sbGVkIFJlc2lkdWFscwo8YnI+CkFub3RoZXIgaW1wb3J0YW50IGZhY3RvciB3ZSB3YW50IHRvIGV4cGxvcmUgaXMgdGhlIGxlbmd0aCBvZiB0aGUgY3JpdGljYWwgaXRlbSEgSW4gb3JkZXIgdG8gYWRkIHRoaXMsIHdlIHNpbXBseSBjcmVhdGUgYSBuZXcgY29sdW1uIDxiPmZvcm1fbGVuZ3RoPC9iPiBhbmQgdGVsbCBSIHRvIGlucHV0IGFzIHRoYXQgY29sdW1uJ3MgdmFsdWUgdGhlIGxlbmd0aCBvZiB0aGUgc3RyaW5nIHRoYXQgYXBwZWFycyBpbiB0aGF0IHJvdydzIDxiPmZvcm08L2I+IGNvbHVtbiwgd2hpY2ggY29ycmVzcG9uZHMgdG8gdGhlIG9ydGhvZ3JhcGljIGZvcm0gb2YgdGhlIGNyaXRpY2FsIGl0ZW0gaW4gdGhhdCB0cmlhbC4gPGk+Tm90ZSB0aGF0IHRoaXMgd2lsbCBpbmNsdWRlIHNwYWNlcyBpbiB0aGUgY291bnQhPC9pPgoKYGBge3J9CmFsbF9kYXRhIDwtIGFsbF9kYXRhICU+JQogIG11dGF0ZShmb3JtX2xlbmd0aCA9IHN0cl9sZW5ndGgoZm9ybSkpCgpzaW1wbGVfbW9kZWwgPC0gbG0obG9nKHJ0KX5mb3JtX2xlbmd0aCwgZGF0YSA9IGFsbF9kYXRhKQoKYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKHJlc2lkX3J0ID0gcmVzaWQoc2ltcGxlX21vZGVsKSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShzaW1wbGVfbW9kZWwpCmBgYAoKCk5vdyB0aGF0IHdlIGhhdmUgdGhlc2UsIHdlIGNhbiBydW4gYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gd2hpY2ggd2lsbCBzaG93IHVzIHRoZSBlZmZlY3Qgb2Ygb3J0aG9ncmFwaGljIGxlbmd0aCBvbiByZWFkaW5nIHRpbWUuIFRoZW4gd2UgYWRkIGEgbmV3IGNvbHVtbiBpbiB0aGUgZGF0YSB3aGljaCBpcyB0aGUgcmVzaWR1YWwgcmVhZGluZyB0aW1lLCBvciB0aGUgcmVhZGluZyB0aW1lIGluIGxvZyBzcGFjZSBBRlRFUiB3ZSBjb250cm9sIGZvciB0aGUgZWZmZWN0cyBvZiBvcnRob2dyYXBoaWMgbGVuZ3RoLgoKIyMjIEFkZGluZyBDb25ncnVlbmN5IENvbHVtbgo8YnI+CldlIGFsc28gd2FudCB0byBtYWtlIHN1cmUgd2UgaGF2ZSBhIGNvbHVtbiB3aGljaCByZWNvcmRzIHdoZXRoZXIgb3Igbm90IHRoZSB0cmlhbCB3YXMgZ2VuZGVyLWNvbmdydWVudCAoYXMgaW4gPGk+J1NoZWxieSBpcyBhIGNvbmdyZXNzd29tYW4nPC9pPikgb3IgZ2VuZGVyIG5ldXRyYWwgKGFzIGluIDxpPidTaGVsYnkgaXMgYSBjb25ncmVzc3BlcnNvbic8L2k+KS4gV2UgYWRkIGEgPGI+dHJpYWxfY29uZ3J1ZW5jeTwvYj4gY29sdW1uLCB3aGljaCBpcyB2YWx1ZWQgYXMgPGk+J2NvbmdydWVudCc8L2k+IGlmIHRoYXQgcm93J3MgY29uZGl0aW9uIGlzIG9uZSBvZiB0aGUgdHdvIGNvbmdydWVudCBjb25kaXRpb25zLiBPdGhlcndpc2UsIGl0IGdldHMgdmFsdWVkIGFzIDxpPiduZXV0cmFsJzwvaT4uCgpgYGB7cn0KYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKHRyaWFsX2NvbmdydWVuY3kgPSBpZmVsc2UoY29uZGl0aW9uPT0nY29uZ3J1ZW50X21hbGUnIHwgY29uZGl0aW9uID09ICdjb25ncnVlbnRfZmVtYWxlJywnY29uZ3J1ZW50JywnbmV1dHJhbCcpKQpgYGAKCiMjIyBBZGRpbmcgTGFyZ2UgUG9saXRpY2FsIE1hY3JvY2F0ZWdvcmllcwo8YnI+CkZpbmFsbHksIHdlIGNhbiBjbGFzc2lmeSBwYXJ0aWNpcGFudHMgYnkgdGhlaXIgcGFydGljdWxhciBwb2xpdGljYWwgYWxpZ25tZW50OyB3ZSBjYW4gY29uc3RydWUgdGhpcyBicm9hZGx5IGFzICJSZXB1YmxpY2FucyIgdnMuICJEZW1vY3JhdHMiLCB3aXRoIHRob3NlIHdobyBkZWNsaW5lZCB0byBzdGF0ZSBhIHByZWZlcmVuY2UsIG9yIHBsYWNlZCB0aGVtc2VsdmVzIGluIHRoZSBtaWRkbGUsIGFzICJOb24tUGFydGlzYW4iLgoKYGBge3J9CmFsbF9kYXRhIDwtIGFsbF9kYXRhICU+JQogIG11dGF0ZShwb2xpX3BhcnR5ID0gaWZlbHNlKHN1YmplY3RfaW5mb3JtYXRpb24ucGFydHlfYWxpZ25tZW50ID09IDEgfCBzdWJqZWN0X2luZm9ybWF0aW9uLnBhcnR5X2FsaWdubWVudCA9PSAyLCdSZXB1YmxpY2FuJyxpZmVsc2Uoc3ViamVjdF9pbmZvcm1hdGlvbi5wYXJ0eV9hbGlnbm1lbnQgPT0gNCB8IHN1YmplY3RfaW5mb3JtYXRpb24ucGFydHlfYWxpZ25tZW50ID09IDUsJ0RlbW9jcmF0JywnTm9uLVBhcnRpc2FuJykpKQpgYGAKCiMgRGF0YSBWaXN1YWxpemF0aW9uCk5vdyB3ZSBjYW4gc3RhcnQgYW5hbHlzaW5nIHRoZSBkYXRhIGJ5IG1lYW5zIG9mIGRhdGEgdmlzdWFsaXphdGlvbi4gCgpgYGB7cn0KaW5hdWd1cmF0aW9uXzIwMjEgPSBjKCIjNTQ0NWIxIiwgIiM3NDlkYWUiLCAiI2YzYzQ4MyIsICIjNWMxYTMzIiwgIiNjZDMzNDEiLCIjZjdkYzZhIikKYGBgCgoKIyMgSWRlb2xvZ3kgYnkgQWdlCgpgYGB7cn0KZ2dwbG90KGFsbF9kYXRhLCBhZXMoeD1zdWJqZWN0X2luZm9ybWF0aW9uLmFnZSwgeT1nZW5kZXJfdG90YWwsIGNvbG9yPXBvbGlfcGFydHkpKSArIAogIGdlb21fcG9pbnQoYWxwaGE9LjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2l6ZT0xLjIpCmBgYAoKIyMgUmVhZGluZyBUaW1lIGJ5IEdlbmRlciBJZGVvbG9neQoKYGBge3J9CmdncGxvdChhbGxfZGF0YSwgYWVzKHg9Z2VuZGVyX3RvdGFsLCB5PXJlc2lkX3J0LCBjb2xvcj10cmlhbF9jb25ncnVlbmN5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhPS41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScsIHNpemU9MS4yKSArIAogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIFJlYWRpbmcgVGltZSBieSBBZ2UKYGBge3J9CmdncGxvdChhbGxfZGF0YSwgYWVzKHg9c3ViamVjdF9pbmZvcm1hdGlvbi5hZ2UsIHk9cmVzaWRfcnQsIGNvbG9yPXRyaWFsX2NvbmdydWVuY3ksIGxpbmV0eXBlPW1vcnBoX3R5cGUpKSArIAogIGdlb21fcG9pbnQoYWxwaGE9LjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2xtJywgc2l6ZT0xLjIpCmBgYAoKIyMgUmVhZGluZyBUaW1lIGJ5IENvbmdydWVuY3kgYW5kIEdlbmRlcgoKYGBge3J9CmFnZ19zcGVha2VyX21lYW5fY29uIDwtIGFsbF9kYXRhICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbix3b3JrZXJpZCkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVD1tZWFuKHJlc2lkX3J0KSkKYGBgCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uLHRyaWFsX2dlbmRlcikgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocmVzaWRfcnQpLCBDSS5Mb3cgPSBjaS5sb3cocmVzaWRfcnQpLCBDSS5IaWdoID0gY2kuaGlnaChyZXNpZF9ydCkpICU+JQogIG11dGF0ZShZTWluID0gTWVhblJUIC0gQ0kuTG93LCBZTWF4ID0gTWVhblJUICsgQ0kuSGlnaCkgJT4lCiAgZ2dwbG90KGFlcyh4PWNvbmRpdGlvbix5PU1lYW5SVCxjb2xvcj10cmlhbF9nZW5kZXIpKSArIAogIGdlb21fcG9pbnQoc2l6ZT0zKSArIAogIGdlb21faml0dGVyKGRhdGEgPSBhZ2dfc3BlYWtlcl9tZWFuX2NvbiwgYWVzKHk9TWVhblJUKSxhbHBoYT0uMSxjb2xvcj0nZGFya3JlZCcpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1ZTWluLHltYXg9WU1heCksIHdpZHRoPS4yNSkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaW5hdWd1cmF0aW9uXzIwMjEpICsgCiAgdGhlbWVfbWluaW1hbCgpCmBgYAojIyBSZWFkaW5nIFRpbWUgYnkgQ29uZ3J1ZW5jeSwgR2VuZGVyLCBhbmQgTGV4aWNhbCBJdGVtCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uLHRyaWFsX2dlbmRlcix0cmlhbF9jb25ncnVlbmN5LGxleGVtZSkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocmVzaWRfcnQpLCBDSS5Mb3cgPSBjaS5sb3cocmVzaWRfcnQpLCBDSS5IaWdoID0gY2kuaGlnaChyZXNpZF9ydCkpICU+JQogIG11dGF0ZShZTWluID0gTWVhblJUIC0gQ0kuTG93LCBZTWF4ID0gTWVhblJUICsgQ0kuSGlnaCkgJT4lCiAgZ2dwbG90KGFlcyh4PWNvbmRpdGlvbix5PU1lYW5SVCxjb2xvcj10cmlhbF9nZW5kZXIsc2hhcGU9dHJpYWxfY29uZ3J1ZW5jeSkpICsgCiAgZ2VvbV9wb2ludChzaXplPTMpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPVlNaW4seW1heD1ZTWF4KSwgd2lkdGg9LjI1KSArIAogIGZhY2V0X3dyYXAofiBsZXhlbWUpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IC43LCBoanVzdD0uNykpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGluYXVndXJhdGlvbl8yMDIxKSArIAogIGZhY2V0X3dyYXAofmxleGVtZSkKYGBgCiMjIyBNYWxlIEFkb3B0aW9ucyBPbmx5CgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZmlsdGVyKG1vcnBoX3R5cGUgPT0gImFkb3B0aW9uIikgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uLHRyaWFsX2dlbmRlcix0cmlhbF9jb25ncnVlbmN5LGxleGVtZSkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocmVzaWRfcnQpLCBDSS5Mb3cgPSBjaS5sb3cocmVzaWRfcnQpLCBDSS5IaWdoID0gY2kuaGlnaChyZXNpZF9ydCkpICU+JQogIG11dGF0ZShZTWluID0gTWVhblJUIC0gQ0kuTG93LCBZTWF4ID0gTWVhblJUICsgQ0kuSGlnaCkgJT4lCiAgZ2dwbG90KGFlcyh4PWNvbmRpdGlvbix5PU1lYW5SVCxjb2xvcj10cmlhbF9nZW5kZXIsc2hhcGU9dHJpYWxfY29uZ3J1ZW5jeSkpICsgCiAgZ2VvbV9wb2ludChzaXplPTMpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPVlNaW4seW1heD1ZTWF4KSwgd2lkdGg9LjI1KSArIAogIGZhY2V0X3dyYXAofiBsZXhlbWUpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IC43LCBoanVzdD0uNykpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGluYXVndXJhdGlvbl8yMDIxKSArIAogIGZhY2V0X3dyYXAofmxleGVtZSkKYGBgCgojIyMgQ29tcG91bmRzIG9ubHkKCmBgYHtyfQphbGxfZGF0YSAlPiUKICBmaWx0ZXIobW9ycGhfdHlwZSA9PSAiY29tcG91bmQiKSAlPiUKICBncm91cF9ieShjb25kaXRpb24sdHJpYWxfZ2VuZGVyLHRyaWFsX2NvbmdydWVuY3ksbGV4ZW1lKSAlPiUKICBzdW1tYXJpemUoTWVhblJUID0gbWVhbihyZXNpZF9ydCksIENJLkxvdyA9IGNpLmxvdyhyZXNpZF9ydCksIENJLkhpZ2ggPSBjaS5oaWdoKHJlc2lkX3J0KSkgJT4lCiAgbXV0YXRlKFlNaW4gPSBNZWFuUlQgLSBDSS5Mb3csIFlNYXggPSBNZWFuUlQgKyBDSS5IaWdoKSAlPiUKICBnZ3Bsb3QoYWVzKHg9Y29uZGl0aW9uLHk9TWVhblJULGNvbG9yPXRyaWFsX2dlbmRlcixzaGFwZT10cmlhbF9jb25ncnVlbmN5KSkgKyAKICBnZW9tX3BvaW50KHNpemU9MykgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49WU1pbix5bWF4PVlNYXgpLCB3aWR0aD0uMjUpICsgCiAgZmFjZXRfd3JhcCh+IGxleGVtZSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gLjcsIGhqdXN0PS43KSkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaW5hdWd1cmF0aW9uXzIwMjEpICsgCiAgZmFjZXRfd3JhcCh+bGV4ZW1lKQpgYGAKCiMjIFJhdyBSZWFkaW5nIFRpbWUgYnkgVHJpYWwgR2VuZGVyCgoKYGBge3J9CnRlbXAgPC0gYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkodHJpYWxfZ2VuZGVyKSAlPiUKICBzdW1tYXJpemUoTWVhblJUID0gbWVhbihydCksIENJLkxvdyA9IGNpLmxvdyhydCksIENJLkhpZ2ggPSBjaS5oaWdoKHJ0KSkgJT4lCiAgbXV0YXRlKFlNaW4gPSBNZWFuUlQgLSBDSS5Mb3csIFlNYXggPSBNZWFuUlQgKyBDSS5IaWdoKQoKZG9kZ2UgPSBwb3NpdGlvbl9kb2RnZSguOSkKZ2dwbG90KGRhdGE9dGVtcCwgYWVzKHg9dHJpYWxfZ2VuZGVyLHk9TWVhblJULGZpbGw9dHJpYWxfZ2VuZGVyKSkgKyAKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScscG9zaXRpb249ZG9kZ2UpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1ZTWluLHltYXg9WU1heCksd2lkdGg9LjI1LHBvc2l0aW9uPWRvZGdlKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnKQpgYGAKYGBge3J9CmRvZGdlID0gcG9zaXRpb25fZG9kZ2UoLjkpCgphbGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkodHJpYWxfZ2VuZGVyKSAlPiUKICBzdW1tYXJpemUoTWVhblJUID0gbWVhbihyZXNpZF9ydCkpICU+JQogIGdncGxvdChhZXMoeD10cmlhbF9nZW5kZXIseT1NZWFuUlQsZmlsbD10cmlhbF9nZW5kZXIpKSArIAogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5Jyxwb3NpdGlvbj1kb2RnZSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpCmBgYAoKIyMgUmVhZGluZyBUaW1lIFJlc2lkdWFscyBieSBDb25ncnVlbmN5IAoKYGBge3J9CmRvZGdlID0gcG9zaXRpb25fZG9kZ2UoLjkpCgphbGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkodHJpYWxfY29uZ3J1ZW5jeSkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocmVzaWRfcnQpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9dHJpYWxfY29uZ3J1ZW5jeSx5PU1lYW5SVCxmaWxsPXRyaWFsX2NvbmdydWVuY3kpKSArIAogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5Jyxwb3NpdGlvbj1kb2RnZSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpCmBgYAoKIyMgQnkgTW9ycGhvbG9naWNhbCBUeXBlIGFuZCBHZW5kZXIKCmBgYHtyfQphbGxfZGF0YSAlPiUKICBncm91cF9ieShjb25kaXRpb24sdHJpYWxfZ2VuZGVyLG1vcnBoX3R5cGUpICU+JQogIHN1bW1hcml6ZShNZWFuUlQgPSBtZWFuKHJlc2lkX3J0KSwgQ0kuTG93ID0gY2kubG93KHJlc2lkX3J0KSwgQ0kuSGlnaCA9IGNpLmhpZ2gocmVzaWRfcnQpKSAlPiUKICBtdXRhdGUoWU1pbiA9IE1lYW5SVCAtIENJLkxvdywgWU1heCA9IE1lYW5SVCArIENJLkhpZ2gpICU+JQogIGdncGxvdChhZXMoeD1jb25kaXRpb24seT1NZWFuUlQsY29sb3I9dHJpYWxfZ2VuZGVyKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MykgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPVlNaW4seW1heD1ZTWF4KSwgd2lkdGg9LjI1KSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBpbmF1Z3VyYXRpb25fMjAyMSkgKyAKICBmYWNldF93cmFwKH5tb3JwaF90eXBlKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCB2anVzdCA9IDAuNSkpCmBgYAoKIyMgVGFzayBGYW1pbGlhcml0eQoKYGBge3J9CmFnZ19zcGVha2VyX3RyaWFsIDwtIGFsbF9kYXRhICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbix3b3JrZXJpZCkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVD1tZWFuKHJlc2lkX3J0KSkKYGBgCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkodHJpYWxfbm8pICU+JQogIHN1bW1hcmlzZShNZWFuUlQgPSBtZWFuKHJ0KSkgJT4lCiAgZ2dwbG90KGFlcyh4PXRyaWFsX25vLHk9TWVhblJUKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBnZW9tX3Ntb290aCgpICsgCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKCiMgTW9kZWwgQW5hbHlzZXMKCiMgVGVzdGluZyBNb2RlbHMKCmBgYHtyfQp0ZXN0X21vZGVsIDwtIGxtKHJlc2lkX3J0fnRyaWFsX2NvbmdydWVuY3kqbW9ycGhfdHlwZSwgZGF0YT1hbGxfZGF0YSkKYGBgCgpgYGB7cn0Kc3VtbWFyeSh0ZXN0X21vZGVsKQpgYGAKYGBge3J9CnRlc3RfbW9kZWwyIDwtIGxtKHJlc2lkX3J0fnRyaWFsX2dlbmRlciwgZGF0YT1hbGxfZGF0YSkKYGBgCgpgYGB7cn0Kc3VtbWFyeSh0ZXN0X21vZGVsMikKYGBgCgpgYGB7cn0KY29tcG91bmRzX29ubHkgPC0gYWxsX2RhdGEgJT4lCiAgZmlsdGVyKG1vcnBoX3R5cGUgPT0gJ2NvbXBvdW5kJykKYGBgCgpgYGB7cn0KY29tcG91bmRzX29ubHkgPC0gY29tcG91bmRzX29ubHkgJT4lCiAgbXV0YXRlKGN0cmlhbF9jb25ncnVlbmN5ID0gYXMubnVtZXJpYyhhcy5mYWN0b3IodHJpYWxfY29uZ3J1ZW5jeSkpLW1lYW4oYXMubnVtZXJpYyhhcy5mYWN0b3IodHJpYWxfY29uZ3J1ZW5jeSkpKSkgJT4lCiAgbXV0YXRlKGN0cmlhbF9nZW5kZXIgPSBhcy5udW1lcmljKGFzLmZhY3Rvcih0cmlhbF9nZW5kZXIpKS1tZWFuKGFzLm51bWVyaWMoYXMuZmFjdG9yKHRyaWFsX2dlbmRlcikpKSkgJT4lCiAgbXV0YXRlKGNnZW5kZXJfbGluayA9IHNjYWxlKGdlbmRlcl9saW5rKSkgJT4lCiAgbXV0YXRlKGNnZW5kZXJfdG90YWwgPSBzY2FsZShnZW5kZXJfdG90YWwpKQpgYGAKCmBgYHtyfQpjb21wb3VuZF9tb2RlbCA8LSBsbWVyKHJlc2lkX3J0fmN0cmlhbF9jb25ncnVlbmN5KmN0cmlhbF9nZW5kZXIqY2dlbmRlcl90b3RhbCArICgxfHdvcmtlcmlkKSArICgxfGxleGVtZSksZGF0YSA9IGNvbXBvdW5kc19vbmx5KQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGNvbXBvdW5kX21vZGVsKQpgYGAKCmBgYHtyfQphZG9wdGlvbnNfb25seSA8LSBhbGxfZGF0YSAlPiUKICBmaWx0ZXIobW9ycGhfdHlwZSA9PSAnYWRvcHRpb24nKQpgYGAKCmBgYHtyfQphZG9wdGlvbnNfb25seSA8LSBhZG9wdGlvbnNfb25seSAlPiUKICBtdXRhdGUoY3RyaWFsX2NvbmdydWVuY3kgPSBhcy5udW1lcmljKGFzLmZhY3Rvcih0cmlhbF9jb25ncnVlbmN5KSktbWVhbihhcy5udW1lcmljKGFzLmZhY3Rvcih0cmlhbF9jb25ncnVlbmN5KSkpKSAlPiUKICBtdXRhdGUoY3RyaWFsX2dlbmRlciA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKHRyaWFsX2dlbmRlcikpLW1lYW4oYXMubnVtZXJpYyhhcy5mYWN0b3IodHJpYWxfZ2VuZGVyKSkpKSAlPiUKICBtdXRhdGUoY2dlbmRlcl9saW5rID0gc2NhbGUoZ2VuZGVyX2xpbmspKSAlPiUKICBtdXRhdGUoY2dlbmRlcl90b3RhbCA9IHNjYWxlKGdlbmRlcl90b3RhbCkpCmBgYAoKYGBge3J9CmFkb3B0aW9uc19tb2RlbCA8LSBsbWVyKHJlc2lkX3J0fmN0cmlhbF9jb25ncnVlbmN5KmN0cmlhbF9nZW5kZXIqY2dlbmRlcl90b3RhbCArICgxfHdvcmtlcmlkKSArICgxfGxleGVtZSkgKyAoMXxuYW1lKSxkYXRhID0gYWRvcHRpb25zX29ubHkpCmBgYAoKYGBge3J9CnN1bW1hcnkoYWRvcHRpb25zX21vZGVsKQpgYGAKCiMjIEZ1bGwgTW9kZWwKCmBgYHtyfQphbGxfZGF0YSA8LSBhbGxfZGF0YSAlPiUKICBtdXRhdGUoY3RyaWFsX2NvbmdydWVuY3kgPSBhcy5udW1lcmljKGFzLmZhY3Rvcih0cmlhbF9jb25ncnVlbmN5KSktbWVhbihhcy5udW1lcmljKGFzLmZhY3Rvcih0cmlhbF9jb25ncnVlbmN5KSkpKSAlPiUKICBtdXRhdGUoY3RyaWFsX2dlbmRlciA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKHRyaWFsX2dlbmRlcikpLW1lYW4oYXMubnVtZXJpYyhhcy5mYWN0b3IodHJpYWxfZ2VuZGVyKSkpKSAlPiUKICBtdXRhdGUoY2dlbmRlcl9saW5rID0gc2NhbGUoZ2VuZGVyX2xpbmspKSAlPiUKICBtdXRhdGUoY2dlbmRlcl90b3RhbCA9IHNjYWxlKGdlbmRlcl90b3RhbCkpICU+JQogIG11dGF0ZShjbW9ycGhfdHlwZSA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKG1vcnBoX3R5cGUpKS1tZWFuKGFzLm51bWVyaWMoYXMuZmFjdG9yKG1vcnBoX3R5cGUpKSkpICU+JQogIG11dGF0ZShjZ2VuZGVyID0gYXMubnVtZXJpYyhhcy5mYWN0b3Ioc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIpKS1tZWFuKGFzLm51bWVyaWMoYXMuZmFjdG9yKHN1YmplY3RfaW5mb3JtYXRpb24uZ2VuZGVyKSkpKQpgYGAKCmBgYHtyfQpjb21wbGV4X21vZGVsIDwtIGxtZXIocmVzaWRfcnR+Y3RyaWFsX2NvbmdydWVuY3kqY3RyaWFsX2dlbmRlcipjZ2VuZGVyX3RvdGFsICsgKDF8d29ya2VyaWQpICsgKDF8bGV4ZW1lKSxkYXRhID0gYWxsX2RhdGEpCmBgYAoKYGBge3J9CnN1bW1hcnkoY29tcGxleF9tb2RlbCkKYGBgCgojIyBHZW5kZXIgVG90YWwKCmBgYHtyfQppZGVvbG9neV9tb2RlbCA8LSBsbWVyKHJlc2lkX3J0fmN0cmlhbF9jb25ncnVlbmN5KmN0cmlhbF9nZW5kZXIqY2dlbmRlcl9saW5rICsgKDF8d29ya2VyaWQpICsgKDF8bGV4ZW1lKSwgZGF0YT1hbGxfZGF0YSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShpZGVvbG9neV9tb2RlbCkKYGBgCgpgYGB7cn0KZ2VuZGVyX21vZGVsIDwtIGxtZXIocmVzaWRfcnR+Y3RyaWFsX2NvbmdydWVuY3kqY3RyaWFsX2dlbmRlcipjZ2VuZGVyICsgKDF8d29ya2VyaWQpICsgKDF8bGV4ZW1lKSxkYXRhID0gYWxsX2RhdGEpCmBgYAoKYGBge3J9CnN1bW1hcnkoZ2VuZGVyX21vZGVsKQpgYGAKCgojIENvbW1lbnRzCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkod29ya2VyaWQscG9saV9wYXJ0eSkgJT4lCiAgc3VtbWFyaXNlKGNvbW1lbnRzID0gcGFzdGUodW5pcXVlKHN1YmplY3RfaW5mb3JtYXRpb24uY29tbWVudHMpKSkgJT4lCiAgc2VsZWN0KHBvbGlfcGFydHksY29tbWVudHMpCmBgYAoKIyBUZXN0aW5nIEdyb3VuZHMKCiMjIENoZWNraW5nIHRoZSB0aW1lcwoKYGBge3J9Cm5ld190b3kgPC0gcmVhZC5jc3YoJ21hemVfdGFza18xLW1lcmdlZC5jc3YnKSAlPiUKICBmaWx0ZXIodHJpYWxfaWQhPSAnZXhhbXBsZScpICU+JQogIGZpbHRlcihyZXNwb25zZV9jb3JyZWN0ICE9IDApICU+JQogIG11dGF0ZSh0cmlhbF9nZW5kZXIgPSBpZmVsc2UoY29uZGl0aW9uPT0nbmV1dHJhbF9mZW1hbGUnIHwgY29uZGl0aW9uID09ICdjb25ncnVlbnRfZmVtYWxlJywnZmVtYWxlJywnbWFsZScpKSAlPiUKICBtdXRhdGUodHJpYWxfY29uZ3J1ZW5jeSA9IGlmZWxzZShjb25kaXRpb249PSdjb25ncnVlbnRfbWFsZScgfCBjb25kaXRpb24gPT0gJ2NvbmdydWVudF9mZW1hbGUnLCdjb25ncnVlbnQnLCduZXV0cmFsJykpCmBgYAoKYGBge3J9Cm5ld190b3kgJT4lCiAgZ3JvdXBfYnkod29yZF9pZHgsdHJpYWxfZ2VuZGVyKSAlPiUKICBzdW1tYXJpemUoTWVhblJUID0gbWVhbihydCkpICU+JQogIGdncGxvdChhZXMoeD13b3JkX2lkeCwgeT1sb2coTWVhblJUKSwgY29sb3I9dHJpYWxfZ2VuZGVyKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQpuZXdfdG95ICU+JQogIGdyb3VwX2J5KHdvcmRfaWR4LHRyaWFsX2dlbmRlcikgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocnQpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9d29yZF9pZHgsIHk9TWVhblJULCBjb2xvcj10cmlhbF9nZW5kZXIpKSArIAogIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludCgpCmBgYAoKYGBge3J9CmFsbF9kYXRhICU+JQogIGZpbHRlcighaXMubmEocG9saV9wYXJ0eSkpICU+JQogIGdyb3VwX2J5KHBvbGlfcGFydHkpICU+JQogIHN1bW1hcml6ZShNZWFuR2VuZGVyVG90YWwgPSBtZWFuKGdlbmRlcl90b3RhbCkpICU+JQogIGdncGxvdChhZXMoeD1wb2xpX3BhcnR5LCB5PU1lYW5HZW5kZXJUb3RhbCkpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgbGFicyh5PSJNZWFuIEdlbmRlciBUb3RhbCIsIHg9IlBvbGl0aWNhbCBQYXJ0eSIpCmBgYAoKYGBge3J9CmFsbF9kYXRhICU+JQogIGZpbHRlcighaXMubmEoc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIpKSAlPiUKICBmaWx0ZXIoc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIgIT0gJycpICU+JQogIGdyb3VwX2J5KHN1YmplY3RfaW5mb3JtYXRpb24uZ2VuZGVyKSAlPiUKICBzdW1tYXJpemUoTWVhbkdlbmRlclRvdGFsID0gbWVhbihnZW5kZXJfdG90YWwpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9c3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIsIHk9TWVhbkdlbmRlclRvdGFsKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICB0aGVtZV9taW5pbWFsKCkgKyAKICBsYWJzKHk9Ik1lYW4gR2VuZGVyIFRvdGFsIiwgeD0iUGFydGljaXBhbnQgR2VuZGVyIikKYGBgCgpSc2NyaXB0IG1lcmdlX3Jlc3VsdHMuUiBtYXplX3Rhc2tfMS1tZXJnZWQuY3N2IGRlbXMgbWF6ZV90YXNrXzItbWVyZ2VkLmNzdiByZXBzCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uLHRyaWFsX2dlbmRlcikgJT4lCiAgZmlsdGVyKHRyaWFsX25vIDwgMTEpICU+JQogIHN1bW1hcml6ZShNZWFuUlQgPSBtZWFuKHJlc2lkX3J0KSwgQ0kuTG93ID0gY2kubG93KHJlc2lkX3J0KSwgQ0kuSGlnaCA9IGNpLmhpZ2gocmVzaWRfcnQpKSAlPiUKICBtdXRhdGUoWU1pbiA9IE1lYW5SVCAtIENJLkxvdywgWU1heCA9IE1lYW5SVCArIENJLkhpZ2gpICU+JQogIGdncGxvdChhZXMoeD1jb25kaXRpb24seT1NZWFuUlQsY29sb3I9dHJpYWxfZ2VuZGVyKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MykgKyAKICBnZW9tX2ppdHRlcihkYXRhID0gYWdnX3NwZWFrZXJfbWVhbl9jb24sIGFlcyh5PU1lYW5SVCksYWxwaGE9LjEsY29sb3I9J2RhcmtyZWQnKSArIAogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49WU1pbix5bWF4PVlNYXgpLCB3aWR0aD0uMjUpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGluYXVndXJhdGlvbl8yMDIxKSArIAogIHRoZW1lX21pbmltYWwoKQpgYGAKCiMjIFRoZSBGbGlnaHQgQXR0ZW5kYW50IFF1ZXN0aW9uIAoKYGBge3J9CmFsbF9kYXRhICU+JQogIGZpbHRlcihsZXhlbWUgPT0gImZsaWdodCBhdHRlbmRhbnQiKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHBvbGlfcGFydHkpKSAlPiUKICBncm91cF9ieShjb25kaXRpb24sdHJpYWxfZ2VuZGVyLHRyaWFsX2NvbmdydWVuY3kscG9saV9wYXJ0eSkgJT4lCiAgc3VtbWFyaXplKE1lYW5SVCA9IG1lYW4ocmVzaWRfcnQpLCBDSS5Mb3cgPSBjaS5sb3cocmVzaWRfcnQpLCBDSS5IaWdoID0gY2kuaGlnaChyZXNpZF9ydCkpICU+JQogIG11dGF0ZShZTWluID0gTWVhblJUIC0gQ0kuTG93LCBZTWF4ID0gTWVhblJUICsgQ0kuSGlnaCkgJT4lCiAgZ2dwbG90KGFlcyh4PWNvbmRpdGlvbix5PU1lYW5SVCxjb2xvcj10cmlhbF9nZW5kZXIsc2hhcGU9dHJpYWxfY29uZ3J1ZW5jeSkpICsgCiAgZ2VvbV9wb2ludChzaXplPTMpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPVlNaW4seW1heD1ZTWF4KSwgd2lkdGg9LjI1KSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gLjcsIGhqdXN0PS43KSkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gaW5hdWd1cmF0aW9uXzIwMjEpICsgCiAgZmFjZXRfd3JhcCh+cG9saV9wYXJ0eSkKYGBgCgpgYGB7cn0KYWxsX2RhdGEgJT4lCiAgZmlsdGVyKGxleGVtZSA9PSAiZmxpZ2h0IGF0dGVuZGFudCIpICU+JQogIGZpbHRlcighaXMubmEoc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIpKSAlPiUKICBncm91cF9ieShjb25kaXRpb24sdHJpYWxfZ2VuZGVyLHRyaWFsX2NvbmdydWVuY3ksc3ViamVjdF9pbmZvcm1hdGlvbi5nZW5kZXIpICU+JQogIHN1bW1hcml6ZShNZWFuUlQgPSBtZWFuKHJlc2lkX3J0KSwgQ0kuTG93ID0gY2kubG93KHJlc2lkX3J0KSwgQ0kuSGlnaCA9IGNpLmhpZ2gocmVzaWRfcnQpKSAlPiUKICBtdXRhdGUoWU1pbiA9IE1lYW5SVCAtIENJLkxvdywgWU1heCA9IE1lYW5SVCArIENJLkhpZ2gpICU+JQogIGdncGxvdChhZXMoeD1jb25kaXRpb24seT1NZWFuUlQsY29sb3I9dHJpYWxfZ2VuZGVyLHNoYXBlPXRyaWFsX2NvbmdydWVuY3kpKSArIAogIGdlb21fcG9pbnQoc2l6ZT0zKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbj1ZTWluLHltYXg9WU1heCksIHdpZHRoPS4yNSkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IC43LCBoanVzdD0uNykpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGluYXVndXJhdGlvbl8yMDIxKSArIAogIGZhY2V0X3dyYXAofnN1YmplY3RfaW5mb3JtYXRpb24uZ2VuZGVyKQpgYGAKCg==